Level 3: KPA (Rev)
This is an Android reversing challenge.
The APK is corrupted such that it cannot be installed. Fortunately, it can still be extracted by apktool
, which allows the compiled bytecode in classes.dex
to be decompiled by JADX.
The decompilation reveals two important classes, com.tisc.kappa.MainActivity
and com.tisc.kappa.sw
.
package com.tisc.kappa;
public class sw {
static {
System.loadLibrary("kappa");
}
public static void a() {
try {
System.setProperty("KAPPA", css());
} catch (Exception unused) {
}
}
private static native String css();
}
The sw
class loads a JNI library called kappa
with a method css
. In the a
method, the native method css
is called and its return value is stored in the system property KAPPA
. In the lib
directory we can find several subdirectories containing libkappa.so
, which is the native library compiled for different architectures.
public void M(String input_string) {
char[] charArray = input_string.toCharArray();
String valueOf = String.valueOf(charArray);
for (int i2 = 0; i2 < 1024; i2++) {
valueOf = N(valueOf, "SHA1");
}
if (!valueOf.equals("d8655ddb9b7e6962350cc68a60e02cc3dd910583")) {
((TextView) findViewById(d.f3935f)).setVisibility(4);
Q(d.f3930a, 3000);
return;
}
char[] input = Arrays.copyOf(charArray, charArray.length);
charArray[0] = (char) ((input[24] * 2) + 1);
charArray[1] = (char) (((input[23] - 1) / 4) * 3);
// Other similar lines of code
charArray[24] = (char) ((input[0] + 1) / 2);
P("The secret you want is TISC{" + String.valueOf(charArray) + "}", "CONGRATULATIONS!", "YAY");
}
The MainActivity
class contains the M
method that takes in an input string, checks it against some hash. If the hash compares correctly, some transformations are performed on the input, which is then printed out concatenated with the flag string.
Making an educated guess, we can assume that the input string should be the return value of the css
function from earlier. Our next task is then to obtain this value.
There are a few ways to accomplish this:
- Analyze
libkappa.so
to find out how thecss
method works. - Make small modifications to the Smali bytecode of the
sw
class such that instead ofSystem.setProperty
, theLog.v
method is called instead, printing the result ofcss()
to the Android logs. In theory, this is much easier because we don't need to reverse thecss
method.
I went with method 2 because I happened to have an Android phone available to run the APK.
Here's the Smali bytecode for the sw.a
method:
.method public static a()V
.registers 2
:try_start_0
const-string v0, "KAPPA"
invoke-static {}, Lcom/tisc/kappa/sw;->css()Ljava/lang/String;
move-result-object v1
invoke-static {v0, v1}, Ljava/lang/System;->setProperty(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
:try_end_9
.catch Ljava/lang/Exception; {:try_start_0 .. :try_end_9} :catch_9
:catch_9
return-void
.end method
In theory, all we need to do is change Ljava/lang/System;->setProperty
to Landroid/util/Log;->v
, then rebuild the APK, the install and run it.
In reality, building an Android app from a broken APK is not so easy. Here's a quick overview of the issues I faced
android:extractNativeLibs="true"
needed to be set in theapplication
tag ofAndroidManifest.xml
a. But
AndroidManifest.xml
is stored in a binary format in the APK, so I used this library to convert between the two.Once the app opened it crashed immediately because Android wasn't happy about it not using a theme derived from
AppCompat
. This was particularly annoying because the answers on StackOverflow did not work. I ended up just copying the Smali code fromsw.a
into the constructor ofMainActivity
so it could at least print the result before crashing.Lots of other issues that I forgot
Final MainActivity.smali
:
.class public Lcom/tisc/kappa/MainActivity;
.super Landroidx/activity/b;
.source "SourceFile"
# direct methods
.method public constructor <init>()V
.locals 2
const-string v0, "KAPPA"
invoke-static {}, Lcom/tisc/kappa/sw;->css()Ljava/lang/String;
move-result-object v1
invoke-static {v0, v1}, Landroid/util/Log;->v(Ljava/lang/String;Ljava/lang/String;)I
invoke-direct {p0}, Landroidx/activity/b;-><init>()V
return-void
.end method
After running the APK, we finally get the result of the css
method: ArBraCaDabra?KAPPACABANA!
. Now, all we need to do is run MainActivity.M
with ArBraCaDabra?KAPPACABANA!
as the input and get the flag: TISC{C0ngr@tS!us0lv3dIT,KaPpA!}